package ycl.security.handler;

import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import ycl.common.constants.RedisConstant;
import ycl.common.constants.SecurityConstant;
import ycl.common.utils.JSONObjectConvertUtil;
import ycl.security.entity.SecurityUser;

import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * token filter
 *
 * @author ycl
 * @date 2022-03-10 13:30:18
 */
@Component
@Slf4j
public class AuthorizationFilter extends OncePerRequestFilter {

	@Resource
	private StringRedisTemplate stringRedisTemplate;
	@Resource
	private AuthProvider authProvider;

	@Override
	protected void doFilterInternal(HttpServletRequest request,
									@NotNull HttpServletResponse response,
									@NotNull FilterChain filterChain)
			throws ServletException, IOException {
		log.info("TokenAuthFilterHandler . doFilterInternal . 内部过滤");
		String token = request.getHeader(SecurityConstant.TOKEN);
		if (StrUtil.isNotBlank(token)) {
			String v = stringRedisTemplate.opsForValue().get(RedisConstant.getLoginUserKey(token));
			SecurityContext context = SecurityContextHolder.getContext();
			if (StrUtil.isNotBlank(v) && context.getAuthentication() == null) {
				SecurityUser user = JSONObjectConvertUtil.convert(v, SecurityUser.class);
				log.info("---------过滤检查--------- id: {}, 用户名: {}", user.getId(), user.getUsername());
				UserDetails details = this.authProvider.retrieveUser(user.getUsername(), null);
				UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(details, null, details.getAuthorities());
				authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
				context.setAuthentication(authentication);
				log.info("---------过滤完成--------- id: {}, 用户名: {}", user.getId(), user.getUsername());
			}
		}
		filterChain.doFilter(request, response);
	}

}
